package com.hjk.common.utils.string;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.*;
import com.hjk.common.utils.check.Check;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author 黄军凯
 * @date : 2019-04-24 17:20
 **/
public class JsonUtils {

    public static final ObjectMapper MAPPER = new ObjectMapper();

    private static final Logger log = LoggerFactory.getLogger(JsonUtils.class);

    /**
     * 读取json文件字符串 成对象
     *
     * @param filePath 文件路径
     * @param clz      生成的对象类型class
     * @param <T>      对象类型
     * @return 对象
     */
    public static <T> T toObjectByFile(String filePath, Class<T> clz) {
        try {
            return MAPPER.readValue(new File(filePath), clz);
        } catch (IOException e) {
            log.error("读取文件{}转化成对象{}失败", filePath, clz.getName(), e);
        }
        return null;
    }
    /**
     * 读取json文件字符串 成对象
     *
     * @param filePath 文件路径
     * @param valueTypeRef      生成的对象类型class
     * @param <T>      对象类型
     * @return 对象
     */
    public static <T> T toObjectByFile(String filePath, TypeReference<T> valueTypeRef) {
        try {
            return MAPPER.readValue(new File(filePath), valueTypeRef);
        } catch (IOException e) {
            log.error("读取文件{}转化成对象{}失败", filePath, valueTypeRef, e);
        }
        return null;
    }
    /**
     * json格式化

     * @return 对象
     */
    public static String jsonFormat(String json) {
        try {
            Object value = MAPPER.readValue(json, Object.class);
            return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(value);
        } catch (IOException e) {
            log.error("格式化json失败", e);
        }
        return null;
    }

    /**
     * json格式化

     * @return 对象
     */
    public static String jsonFormat(Object obj) {
        String toJsonString = toJsonString(obj);
        if (toJsonString == null) {
            return null;
        }
        try {
            Object value = MAPPER.readValue(toJsonString, Object.class);
            return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(value);
        } catch (IOException e) {
            log.error("格式化json失败", e);
        }
        return null;
    }


    /**
     * 获取json字符串某个字段值
     * json {
     * "code": 200,
     * "data": {
     *      "expiresIn": 43199,
     *      "refreshToken": "123",
     *      "token": "123",
     *      "tokenHead": "Bearer ",
     *      data": {
     *      *      "expiresIn": 43199,
     *      *      "refreshToken": "123",
     *      *      "token": "123",
     *      *      "tokenHead": "Bearer "
     *      * }
     * },
     * "message": "操作成功"
     * }
     * filedList : data,token
     * return:123
     *
     * @param json      json字符串
     * @param filedList 属性集合
     * @return 属性值
     */
    public static Optional<String> readFiledValue(String json, String... filedList) {
        //Check.checkIsNotEmpty(filedList, "filedList isEmpty");
        String result = null;
        try {
            JsonNode jsonNode = MAPPER.readTree(json);
            for (String filed : filedList) {
                //字符串类型JsonNode 防止出现 ""str""
                jsonNode = jsonNode instanceof TextNode ? MAPPER.readTree(jsonNode.asText()).get(filed) : jsonNode.get(filed);
            }

            //是数组的情景
            if (jsonNode instanceof ContainerNode && jsonNode.size() > 0) {
                result = jsonNode.toString();
            } else if (jsonNode instanceof NullNode || jsonNode.isNull()) {

            }  else if (jsonNode instanceof TextNode ||
                    jsonNode instanceof NumericNode ||
                    jsonNode instanceof BooleanNode){
                //字符串类型JsonNode 防止出现 ""str""
                //NumericNode  TextNode BooleanNode 等等
                result = jsonNode.asText();
            }
        } catch (Exception e) {
            log.error("json字符串 {} 转化出错：", json, e);
            e.printStackTrace();
        }
        return Optional.ofNullable(result);
    }


    /**
     * bean转化为json字符串
     *
     * @param obj
     * @return
     */
    public static String toJsonString(Object obj) {
        //如果为空返回空
        if (Check.objectIsNull(obj)) {
            return null;
        }
        //如果为字符串 返回字符串
        if (obj.getClass() == String.class) {
            return (String) obj;
        }
        try {
            //把对象转为json字符串
            return MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("对象{}转化出错：", obj, e);

        }
        return null;
    }


    /**
     * 把json字符串转为对象
     *
     * @param json
     * @param tClass
     * @param <T>
     * @return
     */
    public static <T> T toObject(String json, Class<T> tClass) {
        try {
            if (json != null && !"".equals(json)) {
                //json = json.replaceAll("((?<=(:|,|\\{|\\[))\\s*'|'\\s*(?=(:|,|\\}|\\])))","\\\"");
                json = json.replaceAll("((?<=([:,{\\[]))\\s*'|'\\s*(?=([:,}\\]])))", "\\\"");
            }
            return MAPPER.readValue(json, tClass);
        } catch (IOException e) {
            log.error("json{}转化为对象{}出错：", json, tClass.getName(), e);
        }
        return null;
    }


    public static <E> List<E> toList(String json, Class<E> eClass) {
        try {
            return MAPPER.readValue(json, MAPPER.getTypeFactory().constructCollectionType(List.class, eClass));
        } catch (IOException e) {
            log.error("json{}转化为对象{}出错：", json, eClass.getName(), e);
            return null;
        }
    }

    public static <K, V> Map<K, V> toMap(String json, Class<K> kClass, Class<V> vClass) {
        try {
            return MAPPER.readValue(json, MAPPER.getTypeFactory().constructMapType(Map.class, kClass, vClass));
        } catch (IOException e) {
            log.error("json解析出错：" + json, e);
            return null;
        }
    }

    public static <T> T toType(String json, TypeReference<T> type) {
        try {
            return MAPPER.readValue(json, type);
        } catch (IOException e) {
            log.error("json解析出错：" + json, e);
            return null;
        }
    }

}
